package com.qcloud.image.util;

import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;


public class Main {
    private static final Double avatarSpacePer = 0.16;
    private static final Double avatarPer = 0.28;

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        System.loadLibrary("opencv_java320");
        File file = new File("d:/data");
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                test(f.getPath());
            }
        }
    }

    private static void test(String fileName) {
        int index = fileName.lastIndexOf("\\");
        String suffix = index != -1 ? fileName.substring(index + 1) : ".png";
        String xmlfilePath = Main.class.getClassLoader().getResource("lbpcascade_frontalface.xml").getPath().substring(1);
        System.out.println(xmlfilePath);
        int[] rectPosition = detectFace(fileName, xmlfilePath);
        int x = rectPosition[0];
        int y = rectPosition[1];
        int w = rectPosition[2];
        int h = rectPosition[3];
        int[] imgRect = new int[2];
        try {
            imgRect = getImageWidth(fileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (x == 0 || y == 0 || w == 0 || h == 0) {

            x = imgRect[0];
            y = imgRect[1];
            w = (int) (x * avatarPer);
            h = w;
            System.out.println("人脸识别失败:" + fileName + " 采用默认识别");

        }
    }


    public static int[] getImageWidth(String fileName) throws FileNotFoundException, IOException {
        File picture = new File(fileName);
        BufferedImage sourceImg = ImageIO.read(new FileInputStream(picture));
        int[] imgRect = new int[2];
        imgRect[0] = sourceImg.getWidth();
        imgRect[1] = sourceImg.getHeight();
        return imgRect;
    }

    public static int[] detectFace(String fileName, String xmlfilePath) {
        int[] rectPosition = new int[4];
        CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);
        Mat image = Imgcodecs.imread(fileName);
        System.out.println(image.channels());
        Mat hsv = new Mat();
        Imgproc.cvtColor(image,hsv,Imgproc.COLOR_BGR2HSV);
        Mat range = new Mat();
        Core.inRange(hsv,new Scalar(80,0,0),new Scalar(255,255,255),range);
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3,3));
        Mat morp = new Mat();
        Imgproc.morphologyEx(range,morp,Imgproc.MORPH_CLOSE,kernel);
        Imgproc.morphologyEx(range,morp,Imgproc.MORPH_OPEN,kernel);
        List<MatOfPoint> nameContours=OpencvUtil.findContours(morp);
        int index =0;
            double maxArea = 0;
        for (int i = 0; i < nameContours.size(); i++)
        {
            double area=OpencvUtil.area(nameContours.get(i));
            if(area>maxArea){
                index = i;
                maxArea = area;
            }
        }

        Mat cardMask = Mat.zeros(image.rows(), image.cols(),CvType.CV_8UC1);
        String filename = "d:/data/avatar.jpg";
        Rect rect2 = Imgproc.boundingRect(nameContours.get(index));
        Mat roi = new Mat(image,rect2);
        Imgcodecs.imwrite(filename, roi);

       //灰化处理
        Mat grayimage = OpencvUtil.gray(roi);
        //二值化处理
        Mat binaryimage = OpencvUtil.binary(grayimage);
        //腐蚀
        Mat erodeimage = OpencvUtil.erode(binaryimage,3);
        //膨胀
        Mat dilateimage = OpencvUtil.dilate(erodeimage,3);

        Mat carryimage = OpencvUtil.carry(dilateimage);
        //获取头像
        String name=picture(carryimage,roi);
        System.out.print("姓名是："+name);
        return rectPosition;
    }

    /**
     * <p>
     * Title: cutImage
     * </p>
     * <p>
     * Description: 根据原图与裁切size截取局部图片
     * </p>
     *
     * @param srcImg
     *            源图片
     * @param destImg
     *            图片输出流
     * @param rect
     *            需要截取部分的坐标和大小
     */
    public void cutImage(File srcImg, File destImg, java.awt.Rectangle rect) {
        if (srcImg.exists()) {
            java.io.FileInputStream fis = null;
            ImageInputStream iis = null;
            OutputStream output = null;
            try {
                fis = new FileInputStream(srcImg);
                // ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG,
                // JPEG, WBMP, GIF, gif]
                String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
                String suffix = null;
                // 获取图片后缀
                if (srcImg.getName().indexOf(".") > -1) {
                    suffix = srcImg.getName().substring(srcImg.getName().lastIndexOf(".") + 1);
                } // 类型和图片后缀全部小写，然后判断后缀是否合法
                if (suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase() + ",") < 0) {
                    return;
                }
                // 将FileInputStream 转换为ImageInputStream
                iis = ImageIO.createImageInputStream(fis);
                // 根据图片类型获取该种类型的ImageReader
                ImageReader reader = ImageIO.getImageReaders(new FileImageInputStream(srcImg)).next(); // ImageIO.getImageReadersBySuffix(suffix).next();
                reader.setInput(iis, true);
                ImageReadParam param = reader.getDefaultReadParam();
                param.setSourceRegion(rect);
                BufferedImage bi = reader.read(0, param);
                output = new FileOutputStream(destImg);
                ImageIO.write(bi, suffix, output);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fis != null)
                        fis.close();
                    if (iis != null)
                        iis.close();
                    if (output != null)
                        output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
        }
    }

    public void cutImage(String srcImg, String destImg, int x, int y, int width, int height) {
        cutImage(new File(srcImg), new File(destImg), new java.awt.Rectangle(x, y, width, height));
    }

    public static String picture(Mat mat,Mat image){
        Point point1=new Point(mat.cols()*0.62,mat.rows()*0.2);
        Point point2=new Point(mat.cols()*0.62,mat.rows()*0.2);
        Point point3=new Point(mat.cols()*0.95,mat.rows()*0.75);
        Point point4=new Point(mat.cols()*0.95,mat.rows()*0.75);
        List<Point> list=new ArrayList<>();
        list.add(point1);
        list.add(point2);
        list.add(point3);
        list.add(point4);
        Rect name=OpencvUtil.shear(mat,list);

        String filename = "d:/data/name.jpg";
        Mat roi = new Mat(image,name);
        Imgcodecs.imwrite(filename, roi);
        String nameStr = "";
        return nameStr+"\n";
    }

}
